#include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>


using std::cout;
using std::endl;
template<typename T>
class SyncQueue{
    public:
        SyncQueue(int maxSize) :m_maxSize(maxSize), m_needStop(false){}

        void Put(const T &x)
        {
            Add(x);
        }

        void Put(T && x)
        {
            Add(std::forward<T>(x));
        }

        void Take(std::list<T> & list)
        {
            std::unique_lock<std::mutex> locker(m_mutex);
            while (!NotEmpty())
            {
                if(m_needStop) {
                    break;
                }

                m_notEmpty.wait(locker);

            }
            
            if(m_needStop)
                return ;
            list = std::move(m_queue);
            std::cout << "Get Task Cnt : " << list.size() << "\n";
            m_notFull.notify_one();
        }

        void Take(T & t)
        {
            std::unique_lock<std::mutex> locker(m_mutex);
            while (!NotEmpty())
            {
                if(m_needStop) {
                    break;
                }

                m_notEmpty.wait(locker);

            }
            

            if(m_needStop)
                return ;
            t = m_queue.front();
            m_queue.pop_front();
            m_notFull.notify_one();
        }

        void Stop()
        {
            {
                std::lock_guard<std::mutex> locker(m_mutex);
                m_needStop = true;
            }

            m_notFull.notify_all();
            m_notEmpty.notify_all();
        }

        bool Empty()
        {
            std::lock_guard<std::mutex> locker(m_mutex);
            return m_queue.empty();
        }

        bool Full()
        {
            std::lock_guard<std::mutex> locker(m_mutex);
            return m_queue.size() == m_maxSize;
        }

        size_t Size()
        {
            std::lock_guard<std::mutex> locker(m_mutex); //在构造时，互斥对象被调用线程锁定，在销毁时，互斥对象被解锁。
            return m_queue.size();
        }
    private:
        bool NotFull() const
        {
            bool full = m_queue.size() >= m_maxSize;
            if(full) 
                cout << "缓冲区满了， 需要等待。。。" << endl;
            return !full;
        }

        bool NotEmpty() const
        {
            bool empty = m_queue.empty();
            if(empty) {
                cout << "缓冲区空了，需要等待。。。， 异步层的线程ID：" 
                    << std::this_thread::get_id() << endl;
            }

            return !empty;
        }

        template<typename F>
            void Add(F&&x)
            {
                std::unique_lock<std::mutex> locker(m_mutex);
            while (!NotFull())
            {
                if(m_needStop) {
                    break;
                }

                m_notFull.wait(locker);

            }

                // m_notFull.wait(locker, [this](){return m_needStop || NotFull();}); //函数返回false 堵塞，返回true 取消堵塞

                if(m_needStop)
                    return;
                m_queue.push_back(std::forward<F>(x));
                m_notEmpty.notify_one();
            }
    private:
        std::list<T> m_queue; //缓冲区
        std::mutex m_mutex; //互斥量和条件变量结合起来使用
        std::condition_variable m_notEmpty; //不为空的条件变量
        std::condition_variable m_notFull; //没有满的条件变量
        int m_maxSize; //同步队列最大的size
        bool m_needStop; //停止的标志
};
